package com.hzhq.contract.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.hzhq.contract.bean.dto.CompanyDTO;
import com.hzhq.contract.bean.entity.Company;
import com.hzhq.contract.bean.entity.Depart;
import com.hzhq.contract.bean.vo.CompanyVO;
import com.hzhq.contract.bean.vo.DepartVO;
import com.hzhq.contract.bean.vo.RoleVO;
import com.hzhq.contract.convert.CompanyConvertBasic;
import com.hzhq.contract.convert.DepartConvertBasic;
import com.hzhq.contract.result.Result;
import com.hzhq.contract.service.CompanyService;
import com.hzhq.contract.status.DefaultValue;
import com.hzhq.contract.util.Page2ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import javax.validation.groups.Default;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: hzhq1255
 * @mail: hzhq1255@163.com
 * @date: 2021/4/18 15:32
 * @desc:
 */
@Slf4j
@CrossOrigin
@RestController
@ResponseBody
@Api(tags = "公司管理")
@RequestMapping("/api/v1/companies")
public class CompanyController {


    @Autowired
    CompanyService companyService;

    @ApiOperation(value = "公司列表AllList")
    @RequestMapping(value = "",method = RequestMethod.GET)
    private Result<Object> getAllList(){
        List<CompanyVO> companyVOList = companyService.getAllList().stream().map(CompanyConvertBasic.INSTANCE::dtoToVo).collect(Collectors.toList());
        return Result.success(companyVOList);
    }

    @ApiOperation(value = "公司列表Page")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "currentPage",example = "1",value = "当前页",paramType = "path",dataTypeClass = Integer.class, dataType = "Integer"),
            @ApiImplicitParam(name = "pageSize",example = "10",value = "每页个数",paramType = "path",dataTypeClass = Integer.class, dataType = "Integer")
    })
    @ResponseBody
    @RequestMapping(value = "/page/{currentPage}/pageSize/{pageSize}",method = RequestMethod.GET)
    private Result<Object> getAllPage(@PathVariable("currentPage") @NotNull Integer currentPage,
                                      @PathVariable("pageSize") @NotNull Integer pageSize){
        Page<CompanyVO> companyVOPage = companyService.getAllPage(currentPage, pageSize).map(CompanyConvertBasic.INSTANCE::dtoToVo);
        return Result.success(Page2ResultUtil.getPageData(companyVOPage));
    }

    @ApiOperation(value = "searchCompanies")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "currentPage",example = "1",value = "当前页",paramType = "path",dataTypeClass = Integer.class, dataType = "Integer"),
            @ApiImplicitParam(name = "pageSize",example = "10",value = "当前页个数",paramType = "path",dataTypeClass = Integer.class, dataType = "Integer"),
            @ApiImplicitParam(name = "companyName",value = "公司名",paramType = "query",dataTypeClass = String.class, dataType = "String"),
            @ApiImplicitParam(name = "address",value = "地址",paramType = "query",dataTypeClass = String.class, dataType = "String"),
            @ApiImplicitParam(name = "type",value = "类型",paramType = "query",dataTypeClass = String.class, dataType = "String"),
            @ApiImplicitParam(name = "phone",value = "联系电话",paramType = "query",dataTypeClass = String.class, dataType = "String"),
            @ApiImplicitParam(name = "email",value = "电子邮箱",paramType = "query",dataTypeClass = String.class, dataType = "String")
    })
    @RequestMapping(value = "/search/currentPage/{currentPage}/pageSize/{pageSize}", method = RequestMethod.GET)
    @ResponseBody
    private Result<Object> searchPage(@PathVariable("currentPage") @NotNull Integer currentPage,
                                      @PathVariable("pageSize") @NotNull Integer pageSize,
                                      @RequestParam(value = "companyName",required = false) @NotNull String companyName,
                                      @RequestParam(value = "address",required = false) @NotNull String address,
                                      @RequestParam(value = "type",required = false) @NotNull String type,
                                      @RequestParam(value = "phone",required = false) @NotNull String phone,
                                      @RequestParam(value = "email",required = false) @NotNull String email){
        CompanyDTO company = new CompanyDTO();
        if(null != companyName && !"".equals(companyName)){
            company.setCompanyName(companyName);
        }
        if(null != address && !"".equals(address)){
            company.setAddress(address);
        }
        if(null != type && !"".equals(type)){
            company.setType(type);
        }
        if(null != phone && !"".equals(phone)){
            company.setPhone(phone);
        }
        if(null != email && !"".equals(email)){
            company.setEmail(email);
        }
        company.setDeleted(DefaultValue.NOT_DELETED);
        Page<CompanyVO> companyPage = companyService.searchAllPages(company,currentPage,pageSize)
                .map(CompanyConvertBasic.INSTANCE::dtoToVo);
        return Result.successWithData(Page2ResultUtil.getPageData(companyPage));
    }

    @ApiOperation("获取公司page")
    @ResponseBody
    @RequestMapping(value = "/search/query/currentPage/{currentPage}/pageSize/{pageSize}",method = RequestMethod.GET)
    public Result<Object> searchAllPageByQuery(@PathVariable("currentPage") @NotNull Integer currentPage,
                                               @PathVariable("pageSize") @NotNull Integer pageSize,
                                               @RequestParam(value = "keyword",required = false) String keyword){
        final Query query = new Query();
        final Criteria criteria = new Criteria();
        List<Criteria> ands = new ArrayList<>();
        List<Criteria> ors = new ArrayList<>();
        if (keyword != null){
            ors.add(Criteria.where(Company.COMPANY_NAME_FIELD).regex("^.*"+keyword+".*$"));
            ors.add(Criteria.where(Company.ADDRESS_FIELD).regex("^.*"+keyword+".*$"));
            ors.add(Criteria.where(Company.TYPE_FIELD).regex("^.*"+keyword+".*$"));
            ors.add(Criteria.where(Company.ADDRESS_FIELD).regex("^.*"+keyword+".*$"));
            ors.add(Criteria.where(Company.EMAIL_FIELD).regex("^.*"+keyword+".*$"));
            ors.add(Criteria.where(Company.PHONE_FIELD).regex("^.*"+keyword+".*$"));
            criteria.orOperator(ors.toArray(Criteria[]::new));
        }
        ands.add(Criteria.where(Company.DELETED_FIELD).is(DefaultValue.NOT_DELETED));
        criteria.andOperator(ands.toArray(Criteria[]::new));
        query.addCriteria(criteria);
        Page<CompanyVO> companyVOPage = companyService.searchAllPageByQuery(query,currentPage, pageSize).map(CompanyConvertBasic.INSTANCE::dtoToVo);
        return Result.success(Page2ResultUtil.getPageData(companyVOPage));
    }

    @ApiOperation(value = "getOneByName")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "companyName",value = "companyName",paramType = "path",dataTypeClass = String.class, dataType = "String")
    })
    @ResponseBody
    @RequestMapping(value = "/companyName/{companyName}",method = RequestMethod.GET)
    private Result<Object> getOneByName(@PathVariable("companyName") @NotNull String companyName){
        CompanyVO companyVO = CompanyConvertBasic.INSTANCE.dtoToVo(companyService.getOneByCompanyName(companyName));
        if (null == companyVO){
            return Result.error("companyName=" + companyName + "is not existed");
        }
        return Result.success(companyVO);
    }

    @ApiOperation(value = "getOneById")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "companyId",value = "mongo objectId",paramType = "path",dataTypeClass = String.class, dataType = "String")
    })
    @ResponseBody
    @RequestMapping(value = "/companyId/{companyId}",method = RequestMethod.GET)
    private Result<Object> getOneById(@PathVariable("companyId") @NotNull String companyId){
        if (!ObjectId.isValid(companyId)){
            return Result.error("companyId=" + companyId + " is not valid!");
        }
        CompanyVO companyVO = CompanyConvertBasic.INSTANCE.dtoToVo(companyService.getOneByCompanyId(companyId));
        if (null == companyVO){
            return Result.error("companyId=" + companyId + "is not existed");
        }
        return Result.success(companyVO);
    }

    @ApiOperation(value = "修改company")
    @ResponseBody
    @RequestMapping(value = "/update",method = RequestMethod.POST)
    private Result<Object> update(@RequestBody @NotNull CompanyVO companyVO){
        String companyId = companyVO.getCompanyId();
        if (!ObjectId.isValid(companyId)){
            return Result.error("companyId=" + companyId + " is not valid!");
        }
        CompanyDTO companyDTO = companyService.getOneByCompanyId(companyId);
        if (null == companyDTO){
            return Result.error("companyId="+companyVO.getCompanyId()+" is not existed!");
        }
        CompanyDTO saveCompany = companyService.save(CompanyConvertBasic.INSTANCE.voToDto(companyVO));
        if (null == saveCompany){
            return Result.error("save failure");
        }
        return Result.error(CompanyConvertBasic.INSTANCE.dtoToVo(saveCompany));
    }

    @ApiOperation(value = "保存company")
    @ResponseBody
    @RequestMapping(value = "/save",method = RequestMethod.POST)
    private Result<Object> save(@RequestBody @NotNull CompanyDTO companyDTO){
        ObjectId companyId = companyDTO.getCompanyId();
        CompanyDTO currentCompany = companyService.getOneByCompanyName(companyDTO.getCompanyName());
        if (companyId == null){
            if (null != currentCompany){
                return Result.errorWithMsg("该公司已存在");
            }
            companyDTO.setDeleted(DefaultValue.NOT_DELETED);
            return Result.successWithMsgAndData("添加成功",companyService.save(companyDTO).getCompanyId());
        }else {
            if (null == currentCompany){
                return Result.errorWithMsg("该公司不存在");
            }
            BeanUtil.copyProperties(companyDTO,currentCompany,new CopyOptions().ignoreNullValue());
            return Result.successWithMsgAndData("保存成功",companyService.save(currentCompany).getCompanyId());
        }
    }

    @ApiOperation(value = "保存company")
    @ResponseBody
    @RequestMapping(value = "/saveAll",method = RequestMethod.POST)
    private Result<Object> saveAll(@RequestBody @NotNull List<CompanyVO> companyVOList){
        List<CompanyDTO> companyDTOList = new ArrayList<>();
        for (CompanyVO companyVO: companyVOList){
            if (companyVO == null){
                continue;
            }
            if (companyService.getOneByCompanyName(companyVO.getCompanyName()) != null){
                return Result.error("companyName="+companyVO.getCompanyName() + " is existed!");
            }
            companyDTOList.add(companyService.save(CompanyConvertBasic.INSTANCE.voToDto(companyVO)));
        }

        if (companyDTOList.size() == 0){
            return Result.error("save failure");
        }
        return Result.success(companyDTOList.stream().map(e-> e.getCompanyId().toString()).collect(Collectors.toList()));
    }



    @ApiOperation(value = "deleteById")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "companyId",value = "mongo objectId",paramType = "path",dataTypeClass = String.class, dataType = "String")
    })
    @ResponseBody
    @RequestMapping(value = "/delete/companyId/{companyId}",method = RequestMethod.POST)
    private Result<Object> deleteById(@PathVariable("companyId") @NotNull String companyId){
        if (!ObjectId.isValid(companyId)){
            return Result.error("companyId=" + companyId + " is not valid!");
        }
        String deleteId = companyService.deleteById(companyId);
        if (deleteId == null){
            return Result.error("delete failure");
        }
        return Result.success(deleteId);
    }

    @ApiOperation(value = "deleteByName")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "companyName",value = "companyName",paramType = "path",dataTypeClass = String.class, dataType = "String")
    })
    @ResponseBody
    @RequestMapping(value = "/delete/companyName/{companyName}",method = RequestMethod.POST)
    private Result<Object> deleteByName(@PathVariable("companyName") @NotNull String companyName){
        String deleteId = companyService.deleteByName(companyName);
        if (deleteId == null){
            return Result.error("delete failure!");
        }
        return Result.success(deleteId);
    }

    @ApiOperation(value = "deleteByIds")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "companyIds",value = "mongo objectIds",example = "companyId1,companyId2",paramType = "query",dataTypeClass = String.class, dataType = "String")
    })
    @ResponseBody
    @RequestMapping(value = "/deleteAll",method = RequestMethod.POST)
    private Result<Object> deleteByIds(@RequestParam("companyIds") List<String> companyIds){
        for (String companyId: companyIds){
            if (!ObjectId.isValid(companyId)){
                return Result.error("companyId=" + companyId + " is not valid!");
            }
        }
        List<String> deleteIds = companyService.deleteAll(companyIds);
        return Result.success(deleteIds);
    }


}
